{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "53f4ce16",
   "metadata": {},
   "source": [
    "![](./pics/transformer.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dc5e621a",
   "metadata": {},
   "source": [
    " ### 输入部分"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "cf7f3fec",
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "import torch.nn as nn\n",
    "import math\n",
    "from torch.autograd import Variable\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "import numpy as np\n",
    "import torch.nn.functional as F"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "ecdeaf65",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[-0.7165,  0.4672,  1.2562],\n",
      "        [ 0.2864, -1.1136,  1.3654],\n",
      "        [-0.0824,  0.0428, -0.4326],\n",
      "        [-1.4830,  0.3198, -0.0976]], grad_fn=<EmbeddingBackward>)\n",
      "tensor([[ 0.5219, -1.6387,  1.3840],\n",
      "        [-2.2830,  1.9065, -1.7142],\n",
      "        [-1.2566, -1.9542,  1.2844],\n",
      "        [ 1.2372, -1.3971,  1.1849]], grad_fn=<MulBackward0>)\n"
     ]
    }
   ],
   "source": [
    "class Embeddings(nn.Module):\n",
    "    '''文本嵌入层'''\n",
    "    def __init__(self, d_model, vocab, padding_idx=None):\n",
    "        '''\n",
    "        d_model, 词嵌入的维度\n",
    "        vocab, 词表大小\n",
    "        '''\n",
    "        super(Embeddings, self).__init__()\n",
    "        if padding_idx != None:\n",
    "            self.lut = nn.Embedding(vocab, d_model, padding_idx=padding_idx)\n",
    "        else:\n",
    "            self.lut = nn.Embedding(vocab, d_model)\n",
    "        self.d_model = d_model\n",
    "        \n",
    "    def forward(self, x):\n",
    "        return self.lut(x)*math.sqrt(self.d_model)\n",
    "\n",
    "# 测试\n",
    "embedding = nn.Embedding(10, 3, padding_idx=0)\n",
    "x = torch.LongTensor([4,3,2,7])\n",
    "print(embedding(x))\n",
    "\n",
    "em = Embeddings(3,10, padding_idx=0)\n",
    "print(em(x))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "ba834103",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[ 0.9455,  0.5983,  1.1298,  1.1443,  1.6409],\n",
      "        [-0.7669, -0.3509, -0.8023,  0.4262, -1.1596],\n",
      "        [ 1.0845,  0.7524, -0.1587,  1.2245, -1.1421],\n",
      "        [ 0.6974, -0.6543, -1.1576, -0.1693,  0.5364]])\n",
      "tensor([[ 0.0000,  0.7479,  1.4123,  1.4303,  2.0511],\n",
      "        [-0.9586, -0.4386, -0.0000,  0.5328, -1.4495],\n",
      "        [ 1.3556,  0.9406, -0.1983,  1.5307, -1.4277],\n",
      "        [ 0.0000, -0.8179, -1.4470, -0.2116,  0.6705]])\n",
      "tensor([-0.8373, -0.4250,  0.9166,  0.3889])\n",
      "tensor([[-0.8373, -0.4250,  0.9166,  0.3889]])\n",
      "tensor([[-0.8373],\n",
      "        [-0.4250],\n",
      "        [ 0.9166],\n",
      "        [ 0.3889]])\n",
      "4\n",
      "4\n"
     ]
    }
   ],
   "source": [
    "class PositionalEncoding(nn.Module):\n",
    "    '''位置编码器'''\n",
    "    def __init__(self, d_model, dropout, max_len=5000):\n",
    "        super(PositionalEncoding, self).__init__()\n",
    "        self.dropout = nn.Dropout(p=dropout)\n",
    "        \n",
    "        pe = torch.zeros(max_len, d_model)\n",
    "        position = torch.arange(0, max_len).unsqueeze(1)\n",
    "        div_term = torch.exp(torch.arange(0, d_model, 2) * \n",
    "                             -(math.log(10000.0)/d_model)\n",
    "                            )\n",
    "        pe[:, 0::2] = torch.sin(position * div_term)\n",
    "        pe[:, 1::2] = torch.cos(position * div_term)\n",
    "        \n",
    "        pe = pe.unsqueeze(0)\n",
    "        \n",
    "        self.register_buffer('pe', pe)\n",
    "    \n",
    "    def forward(self, x):\n",
    "        x = x+Variable(self.pe[:, :x.size(1)], requires_grad=False)\n",
    "        return self.dropout(x)\n",
    "    \n",
    "# 测试\n",
    "m = nn.Dropout(p=0.2)\n",
    "x = torch.randn(4, 5)\n",
    "print(x)\n",
    "print(m(x))\n",
    "\n",
    "y = torch.randn(4)\n",
    "print(y)\n",
    "print(y.unsqueeze(0))\n",
    "print(y.unsqueeze(1))\n",
    "\n",
    "print(x.size()[0])\n",
    "print(x.size(0))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "d7374789",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 1080x360 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 绘制词汇向量中特征的分布曲线\n",
    "plt.figure(figsize=(15,5))\n",
    "pe = PositionalEncoding(20, 0)\n",
    "\n",
    "y = pe(Variable(torch.zeros(1, 100, 20)))\n",
    "plt.plot(np.arange(100), y[0, :, 4:8].data.numpy())\n",
    "\n",
    "plt.legend([\"dim %d\" % p for p in [4,5,6,7]])\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "77c6fc57",
   "metadata": {},
   "source": [
    "### 编码器"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5ec22a05",
   "metadata": {},
   "source": [
    "#### 1. 掩码张量"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "31103d62",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1,  2,  3],\n",
       "       [ 4,  5,  6],\n",
       "       [ 0,  8,  9],\n",
       "       [ 0,  0, 12]])"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def subsequent_mask(size):\n",
    "    '''掩码张量'''\n",
    "    attn_shape = (1, size, size)\n",
    "    mask = np.triu(np.ones(attn_shape), k=1).astype('uint8')  # 上三角阵\n",
    "    return torch.from_numpy(1-mask)\n",
    "\n",
    "# np.triu演示\n",
    "np.triu([[1,2,3],[4,5,6],[7,8,9],[10,11,12]], k=-1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "fe78fbef",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x24a6b323880>"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 360x360 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize=(5,5))\n",
    "plt.imshow(subsequent_mask(20)[0])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "12b9fb9a",
   "metadata": {},
   "source": [
    "#### 2. 注意力机制"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7c1a1b8d",
   "metadata": {},
   "source": [
    "$$\n",
    "\\text{Attention}(Q,K,V) = \\text{softmax}(\\frac{QK^T}{\\sqrt{d_k}})V\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "68901df8",
   "metadata": {},
   "source": [
    "![](./pics/attention_3.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "28c83f9d",
   "metadata": {},
   "outputs": [],
   "source": [
    "def attention(Q,K,V, mask=None, dropout=None):\n",
    "    d_k = K.size(-1)\n",
    "    scores = torch.matmul(Q, K.transpose(-2, -1)) / math.sqrt(d_k)  # 只关注最后两维，将其他维度视为batch_size\n",
    "    if mask is not None:\n",
    "        scores = scores.masked_fill(mask == 0, -1e9)  # 对mask中等于0的位置进行填充\n",
    "    p_attn = F.softmax(scores, dim=-1)\n",
    "    if dropout is not None:\n",
    "        p_attn = dropout(p_attn)\n",
    "    \n",
    "    return torch.matmul(p_attn, V), p_attn"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "61b17d0d",
   "metadata": {},
   "source": [
    "#### 3.多头注意力机制"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "23dee6ad",
   "metadata": {},
   "source": [
    "![](./pics/multi-head_attention.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "a56667bb",
   "metadata": {},
   "outputs": [],
   "source": [
    "import copy\n",
    "\n",
    "def clones(module, N):\n",
    "    return nn.ModuleList([copy.deepcopy(module) for _ in range(N)])\n",
    "\n",
    "class MultiHeadedAttention(nn.Module):\n",
    "    def __init__(self, head, embedding_dim, dropout=0.1):\n",
    "        super(MultiHeadedAttention, self).__init__()\n",
    "        \n",
    "        assert(embedding_dim%head==0)\n",
    "        self.d_k = embedding_dim // head\n",
    "        self.head = head\n",
    "        \n",
    "        self.linears = clones(nn.Linear(embedding_dim, embedding_dim), 4)\n",
    "        self.attn = None\n",
    "        self.dropout = nn.Dropout(p=dropout)\n",
    "        \n",
    "    def forward(self, Q, K, V, mask=None):\n",
    "        if mask is not None:\n",
    "            mask = mask.unsqueeze(1)\n",
    "        batch_size = Q.size(0)\n",
    "        # 将embedding_dim进行拆分， -1表示句子长度维度\n",
    "        Q,K,V = [model(x).view(batch_size, -1, self.head, self.d_k).transpose(1, 2) for model, x in zip(self.linears, (Q,K,V))]\n",
    "        x, self.attn = attention(Q, K, V, mask=mask, dropout=self.dropout)\n",
    "        # contiguous使得transpose后能够使用view\n",
    "        x = x.transpose(1, 2).contiguous().view(batch_size, -1, self.head*self.d_k)\n",
    "        return self.linears[-1](x)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ac0322be",
   "metadata": {},
   "source": [
    "#### 4. 前馈全连接层"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "f09ea1a0",
   "metadata": {},
   "outputs": [],
   "source": [
    "class PositionwiseFeedForward(nn.Module):\n",
    "    def __init__(self, d_model, d_ff, dropout=0.1):\n",
    "        super(PositionwiseFeedForward, self).__init__()\n",
    "        \n",
    "        self.w1 = nn.Linear(d_model, d_ff)\n",
    "        self.w2 = nn.Linear(d_ff, d_model)\n",
    "        self.dropout = nn.Dropout(dropout)\n",
    "        \n",
    "    def forward(self, x):\n",
    "        return self.w2(self.dropout(F.relu(self.w1(x))))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "96035e95",
   "metadata": {},
   "source": [
    "#### 5. 规范化层"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "e512e2ee",
   "metadata": {},
   "outputs": [],
   "source": [
    "class LayerNorm(nn.Module):\n",
    "    def __init__(self, features, eps=1e-6):\n",
    "        super(LayerNorm, self).__init__()\n",
    "        self.a2 = nn.Parameter(torch.ones(features))\n",
    "        self.b2 = nn.Parameter(torch.zeros(features))\n",
    "        self.eps = eps\n",
    "        \n",
    "    def forward(self, x):\n",
    "        mean = x.mean(-1, keepdim=True)\n",
    "        std = x.std(-1, keepdim=True)\n",
    "        return self.a2*(x-mean)/(std+self.eps) + self.b2"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b0eb2b98",
   "metadata": {},
   "source": [
    "#### 6. 子层连接结构"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "5bf5afda",
   "metadata": {},
   "outputs": [],
   "source": [
    "class SublayerConnection(nn.Module):\n",
    "    def __init__(self, size, dropout=0.1):\n",
    "        super(SublayerConnection, self).__init__()\n",
    "        self.norm = LayerNorm(size)\n",
    "        self.dropout = nn.Dropout(p=dropout)\n",
    "        \n",
    "    def forward(self, x, sublayer):\n",
    "        return x + self.dropout(sublayer(self.norm(x)))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d0d0a96a",
   "metadata": {},
   "source": [
    "#### 7. 编码器层"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "9b1d6256",
   "metadata": {},
   "outputs": [],
   "source": [
    "class EncoderLayer(nn.Module):\n",
    "    def __init__(self, size, self_attn, feed_forward, dropout):\n",
    "        super(EncoderLayer, self).__init__()\n",
    "        self.self_attn = self_attn\n",
    "        self.feed_forward = feed_forward\n",
    "        \n",
    "        self.sublayer = clones(SublayerConnection(size, dropout), 2)\n",
    "        self.size = size\n",
    "        \n",
    "    def forward(self, x, mask):\n",
    "        x = self.sublayer[0](x, lambda x: self.self_attn(x, x, x, mask))  # 自注意力\n",
    "        return self.sublayer[1](x, self.feed_forward)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b8f563ab",
   "metadata": {},
   "source": [
    "#### 8. 编码器"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "37194f01",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Encoder(nn.Module):\n",
    "    def __init__(self, layer, N):\n",
    "        super(Encoder, self).__init__()\n",
    "        self.layers = clones(layer, N)\n",
    "        self.norm = LayerNorm(layer.size)\n",
    "        \n",
    "    def forward(self, x, mask):\n",
    "        for layer in self.layers:\n",
    "            x = layer(x, mask)\n",
    "        return self.norm(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "69aafa5d",
   "metadata": {},
   "source": [
    "### 解码器"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "db9bc696",
   "metadata": {},
   "source": [
    "#### 1. 解码器层"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "80012637",
   "metadata": {},
   "outputs": [],
   "source": [
    "class DecoderLayer(nn.Module):\n",
    "    def __init__(self, size, self_attn, src_attn, feed_forward, dropout):\n",
    "        super(DecoderLayer, self).__init__()\n",
    "        self.size = size\n",
    "        self.self_attn = self_attn\n",
    "        self.src_attn = src_attn\n",
    "        self.feed_forward = feed_forward\n",
    "        self.sublayer = clones(SublayerConnection(size, dropout), 3)\n",
    "        \n",
    "    def forward(self, x, memory, source_mask, target_mask):\n",
    "        m = memory\n",
    "        x = self.sublayer[0](x, lambda x: self.self_attn(x, x, x, target_mask))\n",
    "        x = self.sublayer[1](x, lambda x: self.src_attn(x, m, m, source_mask))\n",
    "        return self.sublayer[2](x, self.feed_forward)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7777c85e",
   "metadata": {},
   "source": [
    "#### 2. 解码器"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "3ebd9e92",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Decoder(nn.Module):\n",
    "    def __init__(self, layer, N):\n",
    "        super(Decoder, self).__init__()\n",
    "        self.layers = clones(layer, N)\n",
    "        self.norm = LayerNorm(layer.size)\n",
    "    def forward(self, x, memory, source_mask, target_mask):\n",
    "        for layer in self.layers:\n",
    "            x = layer(x, memory, source_mask, target_mask)\n",
    "        return self.norm(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b7819408",
   "metadata": {},
   "source": [
    "### 输出部分"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "8745ae17",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Generator(nn.Module):\n",
    "    def __init__(self, d_model, vocab_size):\n",
    "        super(Generator, self).__init__()\n",
    "        self.project = nn.Linear(d_model, vocab_size)\n",
    "        \n",
    "    def forward(self, x):\n",
    "        return F.log_softmax(self.project(x), dim=-1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "202f7617",
   "metadata": {},
   "source": [
    "### 模型构建"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "cf44b45c",
   "metadata": {},
   "outputs": [],
   "source": [
    "class EncoderDecoder(nn.Module):\n",
    "    def __init__(self, encoder, decoder, source_embed, target_embed, generator):\n",
    "        super(EncoderDecoder, self).__init__()\n",
    "        self.encoder = encoder\n",
    "        self.decoder = decoder\n",
    "        self.src_embed = source_embed\n",
    "        self.tgt_embed = target_embed\n",
    "        self.generator = generator\n",
    "    \n",
    "    def forward(self, source, target, source_mask, target_mask):\n",
    "        return self.decode(self.encode(source, source_mask), source_mask, target, target_mask)\n",
    "    \n",
    "    def encode(self, source, source_mask):\n",
    "        return self.encoder(self.src_embed(source), source_mask)\n",
    "    \n",
    "    def decode(self, memory, source_mask, target, target_mask):\n",
    "        return self.decoder(self.tgt_embed(target), memory, source_mask, target_mask)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "efc913dc",
   "metadata": {},
   "outputs": [],
   "source": [
    "def make_model(source_vocab, target_vocab, N=6, d_model=512, d_ff=2048, head=8, dropout=0.1):\n",
    "    c = copy.deepcopy\n",
    "    \n",
    "    attn = MultiHeadedAttention(head, d_model)\n",
    "    ff = PositionwiseFeedForward(d_model, d_ff, dropout)\n",
    "    position = PositionalEncoding(d_model, dropout)\n",
    "    \n",
    "    model = EncoderDecoder(\n",
    "        Encoder(EncoderLayer(d_model, c(attn), c(ff), dropout), N),\n",
    "        Decoder(DecoderLayer(d_model, c(attn), c(attn), c(ff), dropout), N),\n",
    "        nn.Sequential(Embeddings(d_model, source_vocab), c(position)),\n",
    "        nn.Sequential(Embeddings(d_model, target_vocab), c(position)),\n",
    "        Generator(d_model, target_vocab)\n",
    "    )\n",
    "    \n",
    "    for p in model.parameters():\n",
    "        if p.dim() > 1:\n",
    "            nn.init.xavier_uniform_(p)  # 服从均匀分布\n",
    "    return model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "547aba23",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "EncoderDecoder(\n",
      "  (encoder): Encoder(\n",
      "    (layers): ModuleList(\n",
      "      (0): EncoderLayer(\n",
      "        (self_attn): MultiHeadedAttention(\n",
      "          (linears): ModuleList(\n",
      "            (0): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (1): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (2): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (3): Linear(in_features=512, out_features=512, bias=True)\n",
      "          )\n",
      "          (dropout): Dropout(p=0.1, inplace=False)\n",
      "        )\n",
      "        (feed_forward): PositionwiseFeedForward(\n",
      "          (w1): Linear(in_features=512, out_features=2048, bias=True)\n",
      "          (w2): Linear(in_features=2048, out_features=512, bias=True)\n",
      "          (dropout): Dropout(p=0.1, inplace=False)\n",
      "        )\n",
      "        (sublayer): ModuleList(\n",
      "          (0): SublayerConnection(\n",
      "            (norm): LayerNorm()\n",
      "            (dropout): Dropout(p=0.1, inplace=False)\n",
      "          )\n",
      "          (1): SublayerConnection(\n",
      "            (norm): LayerNorm()\n",
      "            (dropout): Dropout(p=0.1, inplace=False)\n",
      "          )\n",
      "        )\n",
      "      )\n",
      "      (1): EncoderLayer(\n",
      "        (self_attn): MultiHeadedAttention(\n",
      "          (linears): ModuleList(\n",
      "            (0): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (1): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (2): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (3): Linear(in_features=512, out_features=512, bias=True)\n",
      "          )\n",
      "          (dropout): Dropout(p=0.1, inplace=False)\n",
      "        )\n",
      "        (feed_forward): PositionwiseFeedForward(\n",
      "          (w1): Linear(in_features=512, out_features=2048, bias=True)\n",
      "          (w2): Linear(in_features=2048, out_features=512, bias=True)\n",
      "          (dropout): Dropout(p=0.1, inplace=False)\n",
      "        )\n",
      "        (sublayer): ModuleList(\n",
      "          (0): SublayerConnection(\n",
      "            (norm): LayerNorm()\n",
      "            (dropout): Dropout(p=0.1, inplace=False)\n",
      "          )\n",
      "          (1): SublayerConnection(\n",
      "            (norm): LayerNorm()\n",
      "            (dropout): Dropout(p=0.1, inplace=False)\n",
      "          )\n",
      "        )\n",
      "      )\n",
      "      (2): EncoderLayer(\n",
      "        (self_attn): MultiHeadedAttention(\n",
      "          (linears): ModuleList(\n",
      "            (0): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (1): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (2): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (3): Linear(in_features=512, out_features=512, bias=True)\n",
      "          )\n",
      "          (dropout): Dropout(p=0.1, inplace=False)\n",
      "        )\n",
      "        (feed_forward): PositionwiseFeedForward(\n",
      "          (w1): Linear(in_features=512, out_features=2048, bias=True)\n",
      "          (w2): Linear(in_features=2048, out_features=512, bias=True)\n",
      "          (dropout): Dropout(p=0.1, inplace=False)\n",
      "        )\n",
      "        (sublayer): ModuleList(\n",
      "          (0): SublayerConnection(\n",
      "            (norm): LayerNorm()\n",
      "            (dropout): Dropout(p=0.1, inplace=False)\n",
      "          )\n",
      "          (1): SublayerConnection(\n",
      "            (norm): LayerNorm()\n",
      "            (dropout): Dropout(p=0.1, inplace=False)\n",
      "          )\n",
      "        )\n",
      "      )\n",
      "      (3): EncoderLayer(\n",
      "        (self_attn): MultiHeadedAttention(\n",
      "          (linears): ModuleList(\n",
      "            (0): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (1): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (2): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (3): Linear(in_features=512, out_features=512, bias=True)\n",
      "          )\n",
      "          (dropout): Dropout(p=0.1, inplace=False)\n",
      "        )\n",
      "        (feed_forward): PositionwiseFeedForward(\n",
      "          (w1): Linear(in_features=512, out_features=2048, bias=True)\n",
      "          (w2): Linear(in_features=2048, out_features=512, bias=True)\n",
      "          (dropout): Dropout(p=0.1, inplace=False)\n",
      "        )\n",
      "        (sublayer): ModuleList(\n",
      "          (0): SublayerConnection(\n",
      "            (norm): LayerNorm()\n",
      "            (dropout): Dropout(p=0.1, inplace=False)\n",
      "          )\n",
      "          (1): SublayerConnection(\n",
      "            (norm): LayerNorm()\n",
      "            (dropout): Dropout(p=0.1, inplace=False)\n",
      "          )\n",
      "        )\n",
      "      )\n",
      "      (4): EncoderLayer(\n",
      "        (self_attn): MultiHeadedAttention(\n",
      "          (linears): ModuleList(\n",
      "            (0): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (1): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (2): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (3): Linear(in_features=512, out_features=512, bias=True)\n",
      "          )\n",
      "          (dropout): Dropout(p=0.1, inplace=False)\n",
      "        )\n",
      "        (feed_forward): PositionwiseFeedForward(\n",
      "          (w1): Linear(in_features=512, out_features=2048, bias=True)\n",
      "          (w2): Linear(in_features=2048, out_features=512, bias=True)\n",
      "          (dropout): Dropout(p=0.1, inplace=False)\n",
      "        )\n",
      "        (sublayer): ModuleList(\n",
      "          (0): SublayerConnection(\n",
      "            (norm): LayerNorm()\n",
      "            (dropout): Dropout(p=0.1, inplace=False)\n",
      "          )\n",
      "          (1): SublayerConnection(\n",
      "            (norm): LayerNorm()\n",
      "            (dropout): Dropout(p=0.1, inplace=False)\n",
      "          )\n",
      "        )\n",
      "      )\n",
      "      (5): EncoderLayer(\n",
      "        (self_attn): MultiHeadedAttention(\n",
      "          (linears): ModuleList(\n",
      "            (0): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (1): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (2): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (3): Linear(in_features=512, out_features=512, bias=True)\n",
      "          )\n",
      "          (dropout): Dropout(p=0.1, inplace=False)\n",
      "        )\n",
      "        (feed_forward): PositionwiseFeedForward(\n",
      "          (w1): Linear(in_features=512, out_features=2048, bias=True)\n",
      "          (w2): Linear(in_features=2048, out_features=512, bias=True)\n",
      "          (dropout): Dropout(p=0.1, inplace=False)\n",
      "        )\n",
      "        (sublayer): ModuleList(\n",
      "          (0): SublayerConnection(\n",
      "            (norm): LayerNorm()\n",
      "            (dropout): Dropout(p=0.1, inplace=False)\n",
      "          )\n",
      "          (1): SublayerConnection(\n",
      "            (norm): LayerNorm()\n",
      "            (dropout): Dropout(p=0.1, inplace=False)\n",
      "          )\n",
      "        )\n",
      "      )\n",
      "    )\n",
      "    (norm): LayerNorm()\n",
      "  )\n",
      "  (decoder): Decoder(\n",
      "    (layers): ModuleList(\n",
      "      (0): DecoderLayer(\n",
      "        (self_attn): MultiHeadedAttention(\n",
      "          (linears): ModuleList(\n",
      "            (0): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (1): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (2): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (3): Linear(in_features=512, out_features=512, bias=True)\n",
      "          )\n",
      "          (dropout): Dropout(p=0.1, inplace=False)\n",
      "        )\n",
      "        (src_attn): MultiHeadedAttention(\n",
      "          (linears): ModuleList(\n",
      "            (0): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (1): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (2): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (3): Linear(in_features=512, out_features=512, bias=True)\n",
      "          )\n",
      "          (dropout): Dropout(p=0.1, inplace=False)\n",
      "        )\n",
      "        (feed_forward): PositionwiseFeedForward(\n",
      "          (w1): Linear(in_features=512, out_features=2048, bias=True)\n",
      "          (w2): Linear(in_features=2048, out_features=512, bias=True)\n",
      "          (dropout): Dropout(p=0.1, inplace=False)\n",
      "        )\n",
      "        (sublayer): ModuleList(\n",
      "          (0): SublayerConnection(\n",
      "            (norm): LayerNorm()\n",
      "            (dropout): Dropout(p=0.1, inplace=False)\n",
      "          )\n",
      "          (1): SublayerConnection(\n",
      "            (norm): LayerNorm()\n",
      "            (dropout): Dropout(p=0.1, inplace=False)\n",
      "          )\n",
      "          (2): SublayerConnection(\n",
      "            (norm): LayerNorm()\n",
      "            (dropout): Dropout(p=0.1, inplace=False)\n",
      "          )\n",
      "        )\n",
      "      )\n",
      "      (1): DecoderLayer(\n",
      "        (self_attn): MultiHeadedAttention(\n",
      "          (linears): ModuleList(\n",
      "            (0): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (1): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (2): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (3): Linear(in_features=512, out_features=512, bias=True)\n",
      "          )\n",
      "          (dropout): Dropout(p=0.1, inplace=False)\n",
      "        )\n",
      "        (src_attn): MultiHeadedAttention(\n",
      "          (linears): ModuleList(\n",
      "            (0): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (1): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (2): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (3): Linear(in_features=512, out_features=512, bias=True)\n",
      "          )\n",
      "          (dropout): Dropout(p=0.1, inplace=False)\n",
      "        )\n",
      "        (feed_forward): PositionwiseFeedForward(\n",
      "          (w1): Linear(in_features=512, out_features=2048, bias=True)\n",
      "          (w2): Linear(in_features=2048, out_features=512, bias=True)\n",
      "          (dropout): Dropout(p=0.1, inplace=False)\n",
      "        )\n",
      "        (sublayer): ModuleList(\n",
      "          (0): SublayerConnection(\n",
      "            (norm): LayerNorm()\n",
      "            (dropout): Dropout(p=0.1, inplace=False)\n",
      "          )\n",
      "          (1): SublayerConnection(\n",
      "            (norm): LayerNorm()\n",
      "            (dropout): Dropout(p=0.1, inplace=False)\n",
      "          )\n",
      "          (2): SublayerConnection(\n",
      "            (norm): LayerNorm()\n",
      "            (dropout): Dropout(p=0.1, inplace=False)\n",
      "          )\n",
      "        )\n",
      "      )\n",
      "      (2): DecoderLayer(\n",
      "        (self_attn): MultiHeadedAttention(\n",
      "          (linears): ModuleList(\n",
      "            (0): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (1): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (2): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (3): Linear(in_features=512, out_features=512, bias=True)\n",
      "          )\n",
      "          (dropout): Dropout(p=0.1, inplace=False)\n",
      "        )\n",
      "        (src_attn): MultiHeadedAttention(\n",
      "          (linears): ModuleList(\n",
      "            (0): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (1): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (2): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (3): Linear(in_features=512, out_features=512, bias=True)\n",
      "          )\n",
      "          (dropout): Dropout(p=0.1, inplace=False)\n",
      "        )\n",
      "        (feed_forward): PositionwiseFeedForward(\n",
      "          (w1): Linear(in_features=512, out_features=2048, bias=True)\n",
      "          (w2): Linear(in_features=2048, out_features=512, bias=True)\n",
      "          (dropout): Dropout(p=0.1, inplace=False)\n",
      "        )\n",
      "        (sublayer): ModuleList(\n",
      "          (0): SublayerConnection(\n",
      "            (norm): LayerNorm()\n",
      "            (dropout): Dropout(p=0.1, inplace=False)\n",
      "          )\n",
      "          (1): SublayerConnection(\n",
      "            (norm): LayerNorm()\n",
      "            (dropout): Dropout(p=0.1, inplace=False)\n",
      "          )\n",
      "          (2): SublayerConnection(\n",
      "            (norm): LayerNorm()\n",
      "            (dropout): Dropout(p=0.1, inplace=False)\n",
      "          )\n",
      "        )\n",
      "      )\n",
      "      (3): DecoderLayer(\n",
      "        (self_attn): MultiHeadedAttention(\n",
      "          (linears): ModuleList(\n",
      "            (0): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (1): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (2): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (3): Linear(in_features=512, out_features=512, bias=True)\n",
      "          )\n",
      "          (dropout): Dropout(p=0.1, inplace=False)\n",
      "        )\n",
      "        (src_attn): MultiHeadedAttention(\n",
      "          (linears): ModuleList(\n",
      "            (0): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (1): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (2): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (3): Linear(in_features=512, out_features=512, bias=True)\n",
      "          )\n",
      "          (dropout): Dropout(p=0.1, inplace=False)\n",
      "        )\n",
      "        (feed_forward): PositionwiseFeedForward(\n",
      "          (w1): Linear(in_features=512, out_features=2048, bias=True)\n",
      "          (w2): Linear(in_features=2048, out_features=512, bias=True)\n",
      "          (dropout): Dropout(p=0.1, inplace=False)\n",
      "        )\n",
      "        (sublayer): ModuleList(\n",
      "          (0): SublayerConnection(\n",
      "            (norm): LayerNorm()\n",
      "            (dropout): Dropout(p=0.1, inplace=False)\n",
      "          )\n",
      "          (1): SublayerConnection(\n",
      "            (norm): LayerNorm()\n",
      "            (dropout): Dropout(p=0.1, inplace=False)\n",
      "          )\n",
      "          (2): SublayerConnection(\n",
      "            (norm): LayerNorm()\n",
      "            (dropout): Dropout(p=0.1, inplace=False)\n",
      "          )\n",
      "        )\n",
      "      )\n",
      "      (4): DecoderLayer(\n",
      "        (self_attn): MultiHeadedAttention(\n",
      "          (linears): ModuleList(\n",
      "            (0): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (1): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (2): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (3): Linear(in_features=512, out_features=512, bias=True)\n",
      "          )\n",
      "          (dropout): Dropout(p=0.1, inplace=False)\n",
      "        )\n",
      "        (src_attn): MultiHeadedAttention(\n",
      "          (linears): ModuleList(\n",
      "            (0): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (1): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (2): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (3): Linear(in_features=512, out_features=512, bias=True)\n",
      "          )\n",
      "          (dropout): Dropout(p=0.1, inplace=False)\n",
      "        )\n",
      "        (feed_forward): PositionwiseFeedForward(\n",
      "          (w1): Linear(in_features=512, out_features=2048, bias=True)\n",
      "          (w2): Linear(in_features=2048, out_features=512, bias=True)\n",
      "          (dropout): Dropout(p=0.1, inplace=False)\n",
      "        )\n",
      "        (sublayer): ModuleList(\n",
      "          (0): SublayerConnection(\n",
      "            (norm): LayerNorm()\n",
      "            (dropout): Dropout(p=0.1, inplace=False)\n",
      "          )\n",
      "          (1): SublayerConnection(\n",
      "            (norm): LayerNorm()\n",
      "            (dropout): Dropout(p=0.1, inplace=False)\n",
      "          )\n",
      "          (2): SublayerConnection(\n",
      "            (norm): LayerNorm()\n",
      "            (dropout): Dropout(p=0.1, inplace=False)\n",
      "          )\n",
      "        )\n",
      "      )\n",
      "      (5): DecoderLayer(\n",
      "        (self_attn): MultiHeadedAttention(\n",
      "          (linears): ModuleList(\n",
      "            (0): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (1): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (2): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (3): Linear(in_features=512, out_features=512, bias=True)\n",
      "          )\n",
      "          (dropout): Dropout(p=0.1, inplace=False)\n",
      "        )\n",
      "        (src_attn): MultiHeadedAttention(\n",
      "          (linears): ModuleList(\n",
      "            (0): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (1): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (2): Linear(in_features=512, out_features=512, bias=True)\n",
      "            (3): Linear(in_features=512, out_features=512, bias=True)\n",
      "          )\n",
      "          (dropout): Dropout(p=0.1, inplace=False)\n",
      "        )\n",
      "        (feed_forward): PositionwiseFeedForward(\n",
      "          (w1): Linear(in_features=512, out_features=2048, bias=True)\n",
      "          (w2): Linear(in_features=2048, out_features=512, bias=True)\n",
      "          (dropout): Dropout(p=0.1, inplace=False)\n",
      "        )\n",
      "        (sublayer): ModuleList(\n",
      "          (0): SublayerConnection(\n",
      "            (norm): LayerNorm()\n",
      "            (dropout): Dropout(p=0.1, inplace=False)\n",
      "          )\n",
      "          (1): SublayerConnection(\n",
      "            (norm): LayerNorm()\n",
      "            (dropout): Dropout(p=0.1, inplace=False)\n",
      "          )\n",
      "          (2): SublayerConnection(\n",
      "            (norm): LayerNorm()\n",
      "            (dropout): Dropout(p=0.1, inplace=False)\n",
      "          )\n",
      "        )\n",
      "      )\n",
      "    )\n",
      "    (norm): LayerNorm()\n",
      "  )\n",
      "  (src_embed): Sequential(\n",
      "    (0): Embeddings(\n",
      "      (lut): Embedding(11, 512)\n",
      "    )\n",
      "    (1): PositionalEncoding(\n",
      "      (dropout): Dropout(p=0.1, inplace=False)\n",
      "    )\n",
      "  )\n",
      "  (tgt_embed): Sequential(\n",
      "    (0): Embeddings(\n",
      "      (lut): Embedding(11, 512)\n",
      "    )\n",
      "    (1): PositionalEncoding(\n",
      "      (dropout): Dropout(p=0.1, inplace=False)\n",
      "    )\n",
      "  )\n",
      "  (generator): Generator(\n",
      "    (project): Linear(in_features=512, out_features=11, bias=True)\n",
      "  )\n",
      ")\n"
     ]
    }
   ],
   "source": [
    "# 测试\n",
    "source_vocab = 11\n",
    "target_vocab = 11\n",
    "N = 6\n",
    "res = make_model(source_vocab, target_vocab, N)\n",
    "print(res)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b32f204c",
   "metadata": {},
   "source": [
    "### 完成一个简单的COPY任务"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "263d6142",
   "metadata": {},
   "outputs": [],
   "source": [
    "from pyitcast.transformer_utils import *"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "e87b0368",
   "metadata": {},
   "outputs": [],
   "source": [
    "def data_generator(V, batch, num_batch):\n",
    "    for i in range(num_batch):\n",
    "        data = torch.from_numpy(np.random.randint(1, V, size=(batch, 10))).long()\n",
    "        data[:, 0] = 1\n",
    "        source = Variable(data, requires_grad=False)\n",
    "        target = Variable(data, requires_grad=False)\n",
    "        \n",
    "        yield Batch(source, target)\n",
    "V = 11\n",
    "batch = 20\n",
    "num_batch = 30"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "71c9a518",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "G:\\miniconda3\\envs\\torchX\\lib\\site-packages\\torch\\nn\\_reduction.py:42: UserWarning: size_average and reduce args will be deprecated, please use reduction='sum' instead.\n",
      "  warnings.warn(warning.format(ret))\n"
     ]
    }
   ],
   "source": [
    "model = make_model(V, V, N=2)\n",
    "model_optimizer = get_std_opt(model)\n",
    "criterion = LabelSmoothing(size=V, padding_idx=0, smoothing=0.0)\n",
    "loss = SimpleLossCompute(model.generator, criterion, model_optimizer)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "0c53390b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# def run(model, loss, epoches=10):\n",
    "#     for epoch in range(epoches):\n",
    "#         model.train()\n",
    "#         run_epoch(data_generator(V, 8, 20), model, loss)\n",
    "#         model.eval()\n",
    "#         run_epoch(data_generator(V, 8, 5), model, loss)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "2f9f23b1",
   "metadata": {},
   "outputs": [],
   "source": [
    "def run(model, loss, epoches=10):\n",
    "    for epoch in range(epoches):\n",
    "        model.train()\n",
    "        run_epoch(data_generator(V, 8, 20), model, loss)\n",
    "        model.eval()\n",
    "        run_epoch(data_generator(V, 8, 5), model, loss)\n",
    "    model.eval()\n",
    "    \n",
    "    # 假定的输入张量\n",
    "    source = Variable(torch.LongTensor([[1,3,2,5,4,6,7,8,9,10]]))\n",
    "    source_mask = Variable(torch.ones(1,1,10))\n",
    "    result = greedy_decode(model, source, source_mask, max_len=10, start_symbol=1)\n",
    "    print(result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "f0628ba2",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch Step: 1 Loss: 1.513832 Tokens per Sec: 455.695526\n",
      "Epoch Step: 1 Loss: 1.154803 Tokens per Sec: 489.744446\n",
      "Epoch Step: 1 Loss: 1.378891 Tokens per Sec: 412.615936\n",
      "Epoch Step: 1 Loss: 0.870322 Tokens per Sec: 494.834595\n",
      "Epoch Step: 1 Loss: 1.258267 Tokens per Sec: 483.217072\n",
      "Epoch Step: 1 Loss: 0.881168 Tokens per Sec: 494.845947\n",
      "Epoch Step: 1 Loss: 1.015343 Tokens per Sec: 481.590729\n",
      "Epoch Step: 1 Loss: 0.583305 Tokens per Sec: 483.147491\n",
      "Epoch Step: 1 Loss: 0.792414 Tokens per Sec: 476.822998\n",
      "Epoch Step: 1 Loss: 0.574390 Tokens per Sec: 500.002716\n",
      "Epoch Step: 1 Loss: 0.986401 Tokens per Sec: 458.600616\n",
      "Epoch Step: 1 Loss: 0.377323 Tokens per Sec: 476.821503\n",
      "Epoch Step: 1 Loss: 0.714361 Tokens per Sec: 484.846252\n",
      "Epoch Step: 1 Loss: 0.288873 Tokens per Sec: 517.982727\n",
      "Epoch Step: 1 Loss: 0.625942 Tokens per Sec: 517.982300\n",
      "Epoch Step: 1 Loss: 0.192917 Tokens per Sec: 521.744507\n",
      "Epoch Step: 1 Loss: 0.703502 Tokens per Sec: 469.054047\n",
      "Epoch Step: 1 Loss: 0.261672 Tokens per Sec: 486.484528\n",
      "Epoch Step: 1 Loss: 0.363782 Tokens per Sec: 421.008606\n",
      "Epoch Step: 1 Loss: 0.257540 Tokens per Sec: 493.150177\n",
      "tensor([[ 1,  3,  2,  5,  4,  6,  7,  8,  9, 10]])\n"
     ]
    }
   ],
   "source": [
    "run(model, loss)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f4fb29dd",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "torchX",
   "language": "python",
   "name": "torchx"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
